﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
using AspSQLProvider;
using PcaWeb.Models;

namespace PcaWeb.Areas.Admin.Models
{
    #region Modelos

    public class RegisterModel
    {
        [Required]
        [Display(Name = "Nombre de usuario")]
        public string RegisterUserName { get; set; }

        [Required]
        [DataType(DataType.EmailAddress)]
        [Display(Name = "Dirección de correo electrónico")]
        public string RegisterEmail { get; set; }

        [Required]
        [ValidatePasswordLength]
        [DataType(DataType.Password)]
        [Display(Name = "Contraseña")]
        public string RegisterPassword { get; set; }

        [DataType(DataType.Password)]
        [Display(Name = "Confirmar contraseña")]
        [System.ComponentModel.DataAnnotations.CompareAttribute("RegisterPassword", ErrorMessage = "La contraseña y la contraseña de confirmación no coinciden.")]
        public string RegisterConfirmPassword { get; set; }

        [Required]
        [MaxLength(50)]
        [MinLength(4)]
        [Display(Name = "Nick")]
        public string RegisterNick { get; set; }

        [Required]
        [MaxLength(200)]
        [MinLength(4)]
        [Display(Name = "Nombre(s)")]
        public string RegisterNombre { get; set; }

        [Required]
        [MaxLength(200)]
        [MinLength(4)]
        [Display(Name = "Apellido(s)")]
        public string RegisterApellido { get; set; }

        [Required]
        [Display(Name = "Zona horaria")]
        public int RegisterZonaHoraria { get; set; }
    }

    public class ChangePasswordUserModel
    {
        [Required]
        public string UserName { get; set; }

        [Required]
        [ValidatePasswordLength]
        [DataType(DataType.Password)]
        [Display(Name = "Nueva contraseña")]
        public string NewPassword { get; set; }

        [DataType(DataType.Password)]
        [Display(Name = "Confirmar la nueva contraseña")]
        [System.ComponentModel.DataAnnotations.CompareAttribute("NewPassword", ErrorMessage = "La nueva contraseña y la contraseña de confirmación no coinciden.")]
        public string ConfirmPassword { get; set; }
    }

    #endregion

    #region Services

    public interface IMembershipService
    {
        MembershipCreateStatus CreateUser(string userName, string password, string email, string nick, string nombre, string apellido, int zonaHorariaId);

        bool ChangePassword(string userName, string newPassword);

        PgMembershipUser Get(string userName);

        List<PgMembershipUser> GetAllUsers(int start, int limit, out int total);

        bool DeleteUser(string userName);

        void UpdateUser(string userName, string email, bool activo, string nick, string nombre, string apellido, int zonaHorariaId);
    }

    public class MembershipService : IMembershipService
    {
        private readonly PgMembershipProvider _provider;

        public MembershipService()
            : this(null)
        {
        }

        public MembershipService(PgMembershipProvider provider)
        {
            _provider = provider ?? (PgMembershipProvider)Membership.Provider;
        }

        public MembershipCreateStatus CreateUser(string userName, string password, string email, string nick, string nombre, string apellido, int zonaHorariaId)
        {
            if (String.IsNullOrEmpty(userName)) throw new ArgumentException("El valor no puede ser NULL ni estar vacío.", "userName");
            if (String.IsNullOrEmpty(password)) throw new ArgumentException("El valor no puede ser NULL ni estar vacío.", "password");
            if (String.IsNullOrEmpty(email)) throw new ArgumentException("El valor no puede ser NULL ni estar vacío.", "email");
            if (String.IsNullOrEmpty(nick)) throw new ArgumentException("El valor no puede ser NULL ni estar vacío.", "nick");
            if (String.IsNullOrEmpty(nombre)) throw new ArgumentException("El valor no puede ser NULL ni estar vacío.", "nombre");
            if (String.IsNullOrEmpty(apellido)) throw new ArgumentException("El valor no puede ser NULL ni estar vacío.", "apellido");

            MembershipCreateStatus status;
            _provider.CreateUser(userName, password, email, null, null, true, null, out status, nick, nombre, apellido, zonaHorariaId);
            return status;
        }

        public bool ChangePassword(string userName, string newPassword)
        {
            return (_provider as PgMembershipProvider).ChangePassword(userName, newPassword);
        }

        public PgMembershipUser Get(string userName)
        {
            return _provider.GetPgUser(userName, false);
        }

        public List<PgMembershipUser> GetAllUsers(int start, int limit, out int total)
        {
            return _provider.GetListUsers(start, limit, out total);
        }

        public bool DeleteUser(string userName)
        {
            return _provider.DeleteUser(userName, true);
        }

        public void UpdateUser(string userName, string email, bool activo, string nick, string nombre, string apellido, int zonaHorariaId)
        {
            PgMembershipUser usrInfo = _provider.GetPgUser(userName, false);
            usrInfo.Email = email;
            usrInfo.IsApproved = activo;
            usrInfo.nick = nick;
            usrInfo.nombre = nombre;
            usrInfo.apellido = apellido;
            usrInfo.zonaHorariaId = zonaHorariaId;

            _provider.UpdatePgUser(usrInfo);
        }
    }

    #endregion

    #region Validation

    public static class MembershipValidation
    {
        public static string ErrorCodeToString(MembershipCreateStatus createStatus)
        {
            // Vaya a http://go.microsoft.com/fwlink/?LinkID=177550 para
            // obtener una lista completa de códigos de estado.
            switch (createStatus)
            {
                case MembershipCreateStatus.DuplicateUserName:
                    return "El nombre de usuario ya existe. Escriba otro nombre de usuario.";

                case MembershipCreateStatus.DuplicateEmail:
                    return "Ya existe un nombre de usuario para esa dirección de correo electrónico. Especifique otra dirección de correo electrónico.";

                case MembershipCreateStatus.InvalidPassword:
                    return "La contraseña especificada no es válida. Escriba un valor de contraseña válido.";

                case MembershipCreateStatus.InvalidEmail:
                    return "La dirección de correo electrónico especificada no es válida. Compruebe el valor e inténtelo de nuevo.";

                case MembershipCreateStatus.InvalidAnswer:
                    return "La respuesta de recuperación de la contraseña especificada no es válida. Compruebe el valor e inténtelo de nuevo.";

                case MembershipCreateStatus.InvalidQuestion:
                    return "La pregunta de recuperación de la contraseña especificada no es válida. Compruebe el valor e inténtelo de nuevo.";

                case MembershipCreateStatus.InvalidUserName:
                    return "El nombre de usuario especificado no es válido. Compruebe el valor e inténtelo de nuevo.";

                case MembershipCreateStatus.ProviderError:
                    return "El proveedor de autenticación devolvió un error. Compruebe los datos especificados e inténtelo de nuevo. Si el problema continúa, póngase en contacto con el administrador del sistema.";

                case MembershipCreateStatus.UserRejected:
                    return "La solicitud de creación de usuario se ha cancelado. Compruebe los datos especificados e inténtelo de nuevo. Si el problema continúa, póngase en contacto con el administrador del sistema.";

                default:
                    return "Error desconocido. Compruebe los datos especificados e inténtelo de nuevo. Si el problema continúa, póngase en contacto con el administrador del sistema.";
            }
        }
    }

    #endregion
}